package com.cjf.aop.runtime.utils;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;

import com.cjf.aop.runtime.AOPManager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * created by cjf
 * on: 2020/3/25
 */
public class PermissionUtils {
    static final String TAG = PermissionUtils.class.getSimpleName();

    private static final List<String> PERMISSIONS = getPermissions();//获取清单文件中的权限列表
    private static PermissionUtils sInstance;

    private FullCallback mFullCallback;

    private Set<String> mPermissions;
    private List<String> mPermissionsRequest;//需要请求授权列表
    private List<String> mPermissionsGranted;//授权列表
    private List<String> mPermissionsDenied;//拒绝授权列表
    private List<String> mPermissionsDeniedForever;//不在询问，拒绝授权列表

    Lazy<PermissionFragment> mPermissionsFragment;

    /**
     * 获取应用权限
     *
     * @return 清单文件中的权限列表
     */
    public static List<String> getPermissions() {
        return getPermissions(AOPManager.getContext().getPackageName());
    }

    /**
     * 获取应用权限
     *
     * @param packageName 包名
     * @return 清单文件中的权限列表
     */
    public static List<String> getPermissions(String packageName) {
        PackageManager pm = AOPManager.getContext().getPackageManager();
        try {
            return Arrays.asList(pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS).requestedPermissions);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    /**
     * 判断权限是否被授予
     *
     * @param permissions 权限
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isGranted(final String... permissions) {
        for (String permission : permissions) {
            if (!isGranted(permission)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isGranted(final String permission) {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.M
                || PackageManager.PERMISSION_GRANTED
                == ContextCompat.checkSelfPermission(AOPManager.getContext(), permission);
    }

    /**
     * 打开应用具体设置
     */
    public static void openAppSettings() {
        Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
        intent.setData(Uri.parse("package:" + AOPManager.getContext().getPackageName()));
        AOPManager.getContext().startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    }

    /**
     * 设置请求权限
     *
     * @param permissions 要请求的权限
     * @return {@link PermissionUtils}
     */
    public PermissionUtils permission(final String... permissions) {
        mPermissions = new LinkedHashSet<>();
        for (String permission : permissions) {
            if (PERMISSIONS.contains(permission)) {
                mPermissions.add(permission);
            }
        }
        return this;
    }

    public PermissionUtils(FragmentManager fragmentManager) {
        if (fragmentManager != null)
            mPermissionsFragment = getLazySingleton(fragmentManager);
        sInstance = this;
    }

    private Lazy<PermissionFragment> getLazySingleton(@NonNull final FragmentManager fragmentManager) {
        return new Lazy<PermissionFragment>() {
            private PermissionFragment permissionsFragment;

            @Override
            public synchronized PermissionFragment get() {
                if (permissionsFragment == null) {
                    permissionsFragment = getPermissionsFragment(fragmentManager);
                }
                return permissionsFragment;
            }
        };
    }

    private PermissionFragment getPermissionsFragment(@NonNull FragmentManager fragmentManager) {
        PermissionFragment permissionsFragment = findPermissionsFragment(fragmentManager);
        boolean isNewInstance = permissionsFragment == null;
        if (isNewInstance) {
            permissionsFragment = new PermissionFragment();
            fragmentManager
                    .beginTransaction()
                    .add(permissionsFragment, TAG)
                    .commitNow();
        }
        return permissionsFragment;
    }

    private PermissionFragment findPermissionsFragment(@NonNull final FragmentManager fragmentManager) {
        return (PermissionFragment) fragmentManager.findFragmentByTag(TAG);
    }

    /**
     * 设置回调
     *
     * @param callback 完整回调接口
     * @return {@link PermissionUtils}
     */
    public PermissionUtils callback(final FullCallback callback) {
        mFullCallback = callback;
        return this;
    }

    /**
     * 开始请求
     */
    public void request() {
        mPermissionsGranted = new ArrayList<>();
        mPermissionsRequest = new ArrayList<>();
        //6.0以下系统,直接回调全部授权
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            mPermissionsGranted.addAll(mPermissions);
            requestCallBack();
        } else {
            for (String permission : mPermissions) {
                if (isGranted(permission)) {
                    mPermissionsGranted.add(permission);
                } else {
                    mPermissionsRequest.add(permission);
                }
            }
            if (mPermissionsRequest.isEmpty()) {
                requestCallBack();
            } else {
                startPermissionGrant();
            }
        }
    }

    /**
     * 开始权限许可授权
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void startPermissionGrant() {
        mPermissionsDenied = new ArrayList<>();
        mPermissionsDeniedForever = new ArrayList<>();
        if (mPermissionsFragment != null)
            mPermissionsFragment.get().requestPermissions(sInstance.mPermissionsRequest.toArray(new String[mPermissionsRequest.size()]));
        else
            PermissionActivity.start(AOPManager.getContext());
    }

    //权限许可回调
    private void onRequestPermissionsResult(FragmentActivity fragment) {
        getPermissionsStatus(fragment);
        requestCallBack();
    }

    //获取权限许可执行后权限状态
    private void getPermissionsStatus(FragmentActivity activity) {
        Iterator<String> iterator = mPermissionsRequest.iterator();
        while (iterator.hasNext()) {
            String permission = iterator.next();
            if (isGranted(permission)) {//权限许可授权
                mPermissionsGranted.add(permission);
                iterator.remove();
            } else {
                if (activity.shouldShowRequestPermissionRationale(permission)) {//拒绝授权
                    mPermissionsDenied.add(permission);
                } else {//拒绝授权，并且不再弹出
                    mPermissionsDeniedForever.add(permission);
                }
            }
        }
    }

    private void requestCallBack() {
        if (mFullCallback != null) {
            if (mPermissionsRequest.size() == 0 && mPermissionsGranted.size() == mPermissions.size()) {
                //全部授权
                mFullCallback.onGranted(mPermissionsGranted);
            } else {
                mFullCallback.onDenied(mPermissionsDeniedForever, mPermissionsDenied, mPermissionsGranted);
            }
            mFullCallback = null;
        }
    }


    public interface FullCallback {
        /**
         * 全部授权
         *
         * @param permissionsGranted 授权列表
         */
        void onGranted(List<String> permissionsGranted);

        /**
         * @param permissionsDeniedForever 不在询问，拒绝授权列表
         * @param permissionsDenied        拒绝授权列表
         * @param permissionsGranted       统一授权列表
         */
        void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied, List<String> permissionsGranted);
    }

    @FunctionalInterface
    public interface Lazy<V> {
        V get();
    }

    public static class PermissionFragment extends Fragment {
        private static final int PERMISSIONS_REQUEST_CODE = 42;

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }

        @TargetApi(Build.VERSION_CODES.M)
        public void requestPermissions(@NonNull String[] permissions) {
            requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (sInstance != null) {
                sInstance.onRequestPermissionsResult(getActivity());
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public static class PermissionActivity extends FragmentActivity {
        public static void start(final Context context) {
            Intent starter = new Intent(context, PermissionActivity.class);
            starter.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(starter);
        }


        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            if (sInstance != null && sInstance.mPermissionsRequest != null) {
                int size = sInstance.mPermissionsRequest.size();
                requestPermissions(sInstance.mPermissionsRequest.toArray(new String[size]), 1);
            }
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (sInstance != null) {
                sInstance.onRequestPermissionsResult(this);
            }
            finish();
        }
    }

    /**
     * 权限申请被拒绝的监听
     */
    public interface OnPermissionDeniedListener {
        /**
         * @param permissionsDeniedForever 不在询问，拒绝授权列表
         * @param permissionsDenied        拒绝授权列表
         * @param permissionsGranted       统一授权列表
         */
        void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied, List<String> permissionsGranted);
    }
}
